import sys
import os
from PyQt5.QtWidgets import (
    QApplication, QMainWindow, QWidget, QVBoxLayout,
    QPushButton, QFileDialog, QProgressDialog, QMessageBox,
    QAction, QDialog, QLineEdit, QLabel, QHBoxLayout, QCheckBox
)
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIcon, QColor, QPalette
from frame_processor import FrameProcessor
# 改变这一行
from visualization import create_frame_stats_plot, create_compare_plot, CompareWidget, AnalyzeWidget, ErrorRateWidget
from progress_dialog import ProgressDialog
from logger import logger
from file_loader_thread import FileLoaderThread
from crash_recovery import CrashRecovery

def get_resource_path(relative_path):
    """获取资源文件的绝对路径"""
    try:
        # PyInstaller创建临时文件夹,将路径存储在_MEIPASS中
        base_path = sys._MEIPASS
    except Exception:
        # 修改这里，确保使用正确的项目根目录
        base_path = os.path.dirname(os.path.abspath(__file__))
    
    return os.path.join(base_path, relative_path)

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        try:
            self.setWindowTitle("帧数据应用软件")
            self.setGeometry(50, 50, 1200, 800)
            
            # 设置程序样式表
            self.setStyleSheet("""
                QMainWindow {
                    background-color: #FFFFFF;
                }
                QToolBar {
                    background-color: #0064c8;
                    border: none;
                    spacing: 8px;
                    padding: 4px;
                    min-height: 40px;
                }
                QToolBar QAction {
                    color: white;
                    padding: 8px 16px;
                }
                QToolButton {
                    color: white;
                    background-color: transparent;
                    border: none;
                    padding: 4px;
                    margin: 0px 2px;
                }
                QToolButton:hover {
                    background-color: #0055a5;
                    border-radius: 4px;
                }
                QTabWidget::pane {
                    border: 1px solid #BBBBBB;
                    background-color: white;
                }
                QTabBar::tab {
                    background-color: #EEEEEE;
                    color: #333333;
                    padding: 8px 16px;
                    margin-right: 2px;
                    border: 1px solid #BBBBBB;
                    border-bottom: none;
                    border-top-left-radius: 4px;
                    border-top-right-radius: 4px;
                }
                QTabBar::tab:selected {
                    background-color: white;
                    border-bottom: none;
                }
                QGroupBox {
                    border: 1px solid #BBBBBB;
                    border-radius: 5px;
                    margin-top: 10px;
                    padding-top: 12px;
                    font-weight: bold;
                }
                QGroupBox::title {
                    subcontrol-origin: margin;
                    subcontrol-position: top center;
                    padding: 0 5px;
                }
                QPushButton {
                    background-color: #0064c8;
                    color: white;
                    border: none;
                    padding: 6px 12px;
                    border-radius: 3px;
                }
                QPushButton:hover {
                    background-color: #0055a5;
                }
                QPushButton:pressed {
                    background-color: #00448a;
                }
                QPushButton:disabled {
                    background-color: #CCCCCC;
                    color: #666666;
                }
                QLineEdit {
                    border: 1px solid #BBBBBB;
                    border-radius: 3px;
                    padding: 4px 8px;
                    background-color: white;
                }
                QTableWidget, QTableView {
                    gridline-color: #DDDDDD;
                    background-color: white;
                    alternate-background-color: #E3F2FD;  /* 浅蓝色背景 */
                    selection-background-color: #2196F3;  /* 选中时的深蓝色 */
                    selection-color: white;
                }
                QHeaderView::section {
                    background-color: #1976D2;  /* 深蓝色表头背景 */
                    color: white;  /* 表头文字颜色 */
                    padding: 6px;
                    border: none;
                    font-weight: bold;
                }
                QHeaderView::section:checked {
                    background-color: #1565C0;  /* 选中时更深的蓝色 */
                }
                QProgressBar {
                    border: 1px solid #BBBBBB;
                    border-radius: 4px;
                    text-align: center;
                    background-color: #F5F5F5;
                }
                QProgressBar::chunk {
                    background-color: #0064c8;
                    width: 10px;
                    margin: 0.5px;
                    border-radius: 3px;
                }
                QStatusBar {
                    background-color: #F5F5F5;
                    border-top: 1px solid #BBBBBB;
                }
            """)
            
            # 初始化组件
            self.central_widget = QWidget()
            self.setCentralWidget(self.central_widget)
            self.layout = QVBoxLayout(self.central_widget)
            
            # 创建文件路径显示区域
            self.create_file_path_area()
            
            # 使用get_resource_path获取schema文件路径
            schema_file = get_resource_path('frame_schema.xml')
            self.frame_processor = FrameProcessor(schema_file)
            
            # 创建工具栏
            self.create_toolbar()
            
            # 初始化显示区域
            self.display_widget = None
            
            # 保存最近的分析结果
            self.current_stats = None
            
            logger.info("主窗口初始化完成")
            
            # 启动时自动显示分析文件界面
            self.analyze_file()
            
        except Exception as e:
            logger.error(f"主窗口初始化失败: {str(e)}")
            raise
            
    def create_file_path_area(self):
        """创建文件路径显示区域"""
        # 创建容器
        self.file_path_container = QWidget()
        file_path_layout = QVBoxLayout(self.file_path_container)
        
        # 创建单文件分析的路径显示
        self.single_file_container = QWidget()
        single_file_layout = QHBoxLayout(self.single_file_container)
        single_file_layout.addWidget(QLabel("当前分析文件："))
        self.single_file_path = QLineEdit()
        self.single_file_path.setReadOnly(True)
        self.single_file_path.setPlaceholderText("未选择文件")
        single_file_layout.addWidget(self.single_file_path)
        
        # 创建文件比对的路径显示
        self.compare_files_container = QWidget()
        
        # 初始时都不显示
        self.single_file_container.hide()
        self.compare_files_container.hide()
        
        # 添加到主布局
        file_path_layout.addWidget(self.single_file_container)
        file_path_layout.addWidget(self.compare_files_container)
        self.layout.addWidget(self.file_path_container)
            
    def create_toolbar(self):
        """创建工具栏"""
        toolbar = self.addToolBar("工具栏")
        
        # 分析文件按钮
        analyze_action = QAction("分析文件", self)
        analyze_action.triggered.connect(self.analyze_file)
        analyze_action.setIcon(QIcon())  # 不使用图标，只显示文字
        toolbar.addAction(analyze_action)
        
        # 比对文件按钮
        compare_action = QAction("比对文件", self)
        compare_action.triggered.connect(self.compare_files)
        compare_action.setIcon(QIcon())  # 不使用图标，只显示文字
        toolbar.addAction(compare_action)

        # 误码率分析按钮
        error_rate_action = QAction("误码率分析", self)
        error_rate_action.triggered.connect(self.error_rate_analysis)
        error_rate_action.setIcon(QIcon())  # 不使用图标，只显示文字
        toolbar.addAction(error_rate_action)
    
    def analyze_file(self):
        """分析单个文件"""
        try:
            # 清除旧的显示
            if self.display_widget:
                self.display_widget.setParent(None)
            
            # 创建分析界面
            analyze_widget = AnalyzeWidget()
            self.display_widget = analyze_widget
            self.layout.addWidget(self.display_widget)
            
        except Exception as e:
            logger.error(f"分析文件失败: {str(e)}")
            QMessageBox.critical(self, "错误", f"分析文件失败: {str(e)}")
    
    def export_report(self):
        """导出统计报表"""
        try:
            if not self.current_stats:
                QMessageBox.warning(self, "警告", "请先分析文件")
                return
                
            file_path, _ = QFileDialog.getSaveFileName(
                self,
                "导出报表",
                "",
                "Excel文件 (*.xlsx);;CSV文件 (*.csv)"
            )
            
            if file_path:
                if not file_path.endswith(('.xlsx', '.csv')):
                    file_path += '.xlsx'  # 默认使用Excel格式
                    
                # 创建进度对话框
                progress = ProgressDialog(self)
                progress.show()
                progress.update_progress(0, "正在生成报表...")
                
                try:
                    # 导出报表
                    self.frame_processor.export_report(self.current_stats, file_path)
                    progress.update_progress(100, "报表导出完成")
                    QMessageBox.information(self, "成功", f"报表已导出到：\n{file_path}")
                    
                finally:
                    progress.close()
                    
        except Exception as e:
            logger.error(f"导出报表失败: {str(e)}")
            QMessageBox.critical(self, "错误", f"导出报表失败: {str(e)}")
            
    def compare_files(self):
        """比对两个文件"""
        try:
            # 显示比对文件路径区域，隐藏单文件分析路径区域
            self.single_file_container.hide()
            self.compare_files_container.show()
            
            # 清除旧的显示
            if self.display_widget:
                self.display_widget.setParent(None)
            
            # 直接使用CompareWidget作为显示容器
            self.display_widget = CompareWidget()
            self.layout.addWidget(self.display_widget)
            
        except Exception as e:
            logger.error(f"比对文件失败: {str(e)}")
            QMessageBox.critical(self, "错误", f"比对文件失败: {str(e)}")
    
    def export_comparison_report(self):
        """导出比对分析报表"""
        try:
            if not hasattr(self, 'current_comparison'):
                QMessageBox.warning(self, "警告", "请先进行文件比对")
                return
            
            file_path, _ = QFileDialog.getSaveFileName(
                self,
                "导出比对报表",
                "",
                "Excel文件 (*.xlsx);;CSV文件 (*.csv)"
            )
            
            if file_path:
                if not file_path.endswith(('.xlsx', '.csv')):
                    file_path += '.xlsx'  # 默认使用Excel格式
                    
                progress = ProgressDialog(self)
                progress.show()
                
                try:
                    # 导出比对报表，修改为只传递必要的参数
                    self.frame_processor.export_comparison_report(
                        self.current_comparison['comparison'],
                        file_path
                    )
                    progress.update_progress(100, "报表导出完成")
                    QMessageBox.information(self, "成功", f"比对报表已导出到：\n{file_path}")
                    
                finally:
                    progress.close()
                    
        except Exception as e:
            logger.error(f"导出比对报表失败: {str(e)}")
            QMessageBox.critical(self, "错误", f"导出比对报表失败: {str(e)}")

    def error_rate_analysis(self):
        """误码率分析界面"""
        try:
            # 显示误码率分析路径区域，隐藏其他路径区域
            self.single_file_container.hide()
            self.compare_files_container.hide()
            
            # 清除旧的显示
            if self.display_widget:
                self.display_widget.setParent(None)
            
            # 创建误码率分析界面
            error_rate_widget = ErrorRateWidget()
            self.display_widget = error_rate_widget
            self.layout.addWidget(self.display_widget)
            
        except Exception as e:
            logger.error(f"显示误码率分析界面失败: {str(e)}")
            QMessageBox.critical(self, "错误", f"显示误码率分析界面失败: {str(e)}")

    def open_file(self):
        """打开文件"""
        try:
            file_path, _ = QFileDialog.getOpenFileName(
                self,
                "选择帧数据文件",
                "",
                "所有文件 (*.*)"
            )
            
            if file_path:
                # 创建并显示进度对话框
                progress = ProgressDialog(self)
                progress.setWindowTitle("正在加载文件")
                progress.show()
                
                # 初始化帧处理器
                if not self.frame_processor:
                    self.frame_processor = FrameProcessor("frame_schema.xml")
                
                # 创建文件加载线程
                self.loader_thread = FileLoaderThread(self.frame_processor, file_path)
                
                # 连接信号
                self.loader_thread.progress_signal.connect(
                    lambda value, status, detail: progress.update_progress(value, status, detail)
                )
                
                # 处理完成信号
                def on_load_finished(frames):
                    self.frames = frames
                    
                    # 更新状态
                    progress.update_progress(60, "正在分析数据...")
                    
                    # 分析帧数据
                    self.current_stats = self.frame_processor.analyze_frames(self.frames, file_path)
                    
                    # 创建统计图表
                    progress.update_progress(80, "正在生成图表...")
                    plot_widget = create_frame_stats_plot(self.current_stats, self.frames)
                    
                    # 清除旧的显示内容
                    for i in reversed(range(self.plot_layout.count())): 
                        item = self.plot_layout.itemAt(i)
                        if item and item.widget():
                            item.widget().setParent(None)
                    
                    # 显示新的统计结果
                    self.plot_layout.addWidget(plot_widget)
                    
                    # 更新状态栏
                    self.statusbar.showMessage(f"已加载文件：{file_path}")
                    
                    progress.update_progress(100, "处理完成")
                    # 延迟关闭进度对话框，确保界面渲染完成
                    progress.complete_and_close()
                
                # 处理错误信号
                def on_load_error(error_msg):
                    progress.close()
                    QMessageBox.critical(self, "错误", f"加载文件失败: {error_msg}")
                
                # 处理取消操作
                def on_cancel_requested():
                    self.loader_thread.cancel()
                
                # 连接信号
                self.loader_thread.finished_signal.connect(on_load_finished)
                self.loader_thread.error_signal.connect(on_load_error)
                progress.canceled.connect(on_cancel_requested)
                
                # 开始加载
                self.loader_thread.start()
                
        except Exception as e:
            self.logger.error(f"打开文件失败: {str(e)}")
            QMessageBox.critical(self, "错误", f"打开文件失败: {str(e)}")

def main():
    try:
        # 初始化崩溃恢复管理器
        crash_recovery = CrashRecovery()
        
        # 检查崩溃历史
        if not crash_recovery.check_crash_history():
            # 显示崩溃信息
            crash_info = crash_recovery.get_crash_info()
            if crash_info:
                app = QApplication(sys.argv)
                QMessageBox.critical(
                    None, 
                    "程序启动失败", 
                    f"程序在{crash_info['time_window']}秒内崩溃了{crash_info['crash_count']}次。\n"
                    f"最后一次崩溃时间：{crash_info['last_crash']}\n"
                    f"请等待{int(crash_info['can_retry_in'])}秒后再试，或检查以下问题：\n\n"
                    "1. 内存不足 - 请关闭其他程序\n"
                    "2. 文件过大 - 请尝试使用较小的文件\n"
                    "3. 系统资源不足 - 请重启计算机"
                )
                sys.exit(1)
        
        app = QApplication(sys.argv)
        
        # 设置异常钩子，捕获未处理的异常
        def exception_hook(exctype, value, traceback):
            logger.error(f"未处理的异常: {exctype.__name__}: {value}", exc_info=(exctype, value, traceback))
            QMessageBox.critical(None, "程序错误", f"发生未处理的错误：\n{exctype.__name__}: {value}")
        
        sys.excepthook = exception_hook
        
        window = MainWindow()
        window.show()
        
        # 成功启动后记录
        crash_recovery.record_successful_start()
        
        sys.exit(app.exec_())
        
    except MemoryError as e:
        logger.error(f"内存不足错误: {str(e)}")
        if 'app' in locals():
            QMessageBox.critical(None, "内存不足", 
                               "程序因内存不足而无法运行。\n\n"
                               "请尝试：\n"
                               "1. 关闭其他占用内存的程序\n"
                               "2. 使用较小的文件进行分析\n"
                               "3. 重启计算机后再试")
        sys.exit(1)
    except Exception as e:
        logger.error(f"程序运行失败: {str(e)}", exc_info=True)
        if 'app' in locals():
            QMessageBox.critical(None, "启动失败", f"程序启动失败：\n{str(e)}")
        raise

if __name__ == '__main__':
    # 当使用 PyInstaller/cx_Freeze 打包并在 Windows 上启用多进程时，
    # 子进程会重新执行入口脚本。调用 freeze_support() 可阻止子进程
    # 再次创建 GUI 窗口，避免在无响应或并行计算时自动弹出多个实例。
    import multiprocessing as _mp
    try:
        _mp.freeze_support()
    except (RuntimeError, AttributeError):
        # 在普通解释器或不需要 freeze_support 的环境下忽略
        pass

    main()